﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.Data.Linq.Mapping;
using System.Linq.Expressions;
using System.Configuration;
using System.Data.Linq;

namespace VemTransporte.Models.Persistencia
{
    public class GenericDAO<E, K> where E : class
    {
        //private VemTransporteDataContextDataContext context = new VemTransporteDataContextDataContext(ConfigurationManager.ConnectionStrings["VemTransporteConnectionString"].ConnectionString);
        private DataContext context = new DataContext(ConfigurationManager.ConnectionStrings["VemTransporteConnectionString"].ConnectionString);

        public DataContext Context
        {
            get 
            {
                return context; 
            }
            set 
            { 
                context = value;
            }
        }

        /// <summary>
        /// Save (insert or update as appropriate) <paramref name="entity"/> on next commit of the unit of work.
        /// </summary>
        /// <param name="entity">Entity to be saved.</param>
        public virtual void Salvar(E instance)
        {
             object id = instance.GetType().GetProperty("Id").GetValue(instance,null);
             if (id.Equals(0))
             {

                this.Insert(instance);
             }
             else
             {
                 context.Refresh(RefreshMode.KeepCurrentValues, this);

                 this.Salvar();
             }
        }

        public virtual void Salvar()
        {

            context.SubmitChanges();
        }

        public virtual List<E> SelectAll()
        {
            return context.GetTable<E>().ToList();
        }

        public virtual void Insert(E instance)
        {

            context.GetTable<E>().InsertOnSubmit(instance);

            //Console.Write("Total changes: {0}", cs);  
            //// Freeze the console window.
            //Console.ReadLine();

            context.SubmitChanges();
            
        }

        public virtual void Remover(E instance)
        {
            context.GetTable<E>().DeleteOnSubmit(instance);
            context.SubmitChanges();
        }

        public virtual String GetKeyProperty()
        {
            return "Id";
        }

        public virtual Expression<Func<E, bool>> GetKeyLambda(K id)
        {

            var parameter = Expression.Parameter(typeof(E), "e");

            var propId = Expression.Property(parameter, typeof(E).GetProperty(GetKeyProperty()));

            return Expression.Lambda<Func<E, bool>>(Expression.Equal(propId, Expression.Constant(id)), parameter);
        }

        public E ProcurarPorId(K id)
        {
            return context.GetTable<E>().Single(GetKeyLambda(id));
        } 

        //PropertyInfo objectKey;

        #region PRIMARYKEY
        //public static PropertyInfo GetPrimaryKey<TEntity>(string keyPropertyName)
        //{
        //    PropertyInfo[] infos = typeof(TEntity).GetProperties();
        //    foreach (PropertyInfo info in infos)
        //    {
        //        if (info.Name.Equals(keyPropertyName)) return info;
        //    }
        //    return null;
        //}
        //private static PropertyInfo GetPrimaryKey<TEntity>()
        //{
        //    PropertyInfo[] infos = typeof(TEntity).GetProperties();
        //    PropertyInfo PKProperty = null;
        //    foreach (PropertyInfo info in infos)
        //    {
        //        var propsWithColAttr = info.GetCustomAttributes(false).Where(x => x.GetType() == typeof(ColumnAttribute));
        //        var column = propsWithColAttr.FirstOrDefault(x => ((ColumnAttribute)x).IsPrimaryKey && ((ColumnAttribute)x).DbType.Contains("NOT NULL"));
        //        if (column != null)
        //        {
        //            PKProperty = info;
        //            break;
        //        }
        //    }
        //    if (PKProperty == null)
        //    {
        //        throw new NotSupportedException(
        //          typeof(TEntity).ToString() + " has no Primary Key");
        //    }
        //    return PKProperty;
        //}
        #endregion

        //private Expression<Func<E, bool>> getLambaKey(int id)
        //{

        //    var parameter = Expression.Parameter(typeof(E), "e");

        //    PropertyInfo p = GetPrimaryKey<E>();

        //    var propId = Expression.Property(parameter, GetPrimaryKey<E>());

        //    return Expression.Lambda<Func<E, bool>>(Expression.Equal(propId, Expression.Constant(id)), parameter);
        //}
    }
}